/**
 * 
 */
#include "./device_manager.h"
#include "../driver/common/common_modbus.h"
#include "../driver/common/common_modbus_485_port.h"
#include "../bsp/cli_cmd.h"

#ifndef NULL
#define NULL ((void *)0)
#endif

/* 总线属性 */
static struct modbus_485_attr modbus_485_attr[] = {
#if (XP_CONFIG_WASHCAR_ENABLE == 1)
    {.port = 1, .baudrate = 115200 / 2400, .parity = 0, .timeout = 100 / 10},
#elif (XP_CONFIG_DRYER_ENABLE == 1)
    {.port = 1, .baudrate = 19200 / 2400, .parity = 0, .timeout = 100 / 10},
#endif
    {.port = 2, .baudrate = 115200 / 2400, .parity = 0, .timeout = 100 / 10}};

static struct xp_modbus_bus xp_modbus_485_port[] = {
    {
        .name = "modbus_485_port1",
        .port = 1,
        .sid_set = {0},
        .num_of_dev = 0,
        .private_data = (void *)&modbus_485_attr[0],
    },
    {
        .name = "modbus_485_port2",
        .port = 2,
        .sid_set = {0},
        .num_of_dev = 0,
        .private_data = (void *)&modbus_485_attr[1],
    }
};

static struct xp_modbus_bus *xp_modbus_485_port1 = &xp_modbus_485_port[0];
static struct xp_modbus_bus *xp_modbus_485_port2 = &xp_modbus_485_port[1];

static int xp_modbus_485_port_init()
{
    int ret1 = xp_modbus_485_constructor(xp_modbus_485_port1);
    if (ret1 != 0)
    {
        println("xp_modbus_485_port1 init faild.");
    }
    int ret2 = 0;
    /*
    int ret2 = xp_modbus_485_constructor(xp_modbus_485_port2);
    if (ret2 != 0) {
        println("xp_modbus_485_port1 init faild.");
    }
    */

    return (ret1 == 0 && ret2 == 0) ? 0 : (-1);
}

#if (XP_CONFIG_AGV_WHEEL_RS7020_ENABLE == 1)
#include "../driver/leisai-485/rs7020.h"
struct rs7020_motor_attr rs7020_lwheel_attr = {
    .dir = motor_forward,
    .rpm = 0,
    .acc = 500,
    .dec = 500,
};
struct rs7020_motor_attr rs7020_rwheel_attr = {
    .dir = motor_forward,
    .rpm = 0,
    .acc = 500,
    .dec = 500,
};
#elif (XP_CONFIG_AGV_WHEEL_DMKE_ENABLE == 1)
#include "../driver/dmke/dmke.h"
struct dmke_motor_attr dmke_lwheel_attr = {
    .dir = 0, .rpm = 0,
    .control_mode = 0,  // 0 为IO控制  1为485控制
    .io_ctrl = 0,       // IO控制对应的IO输出口
    .io_dir = 1,
    .io_emerg = 2
};
struct dmke_motor_attr dmke_rwheel_attr = {
    .dir = 0, .rpm = 0,
    .control_mode = 0,  // 0 为IO控制  1为485控制
    .io_ctrl = 3,       // IO控制对应的IO输出口
    .io_dir = 6,
    .io_emerg = 5
};
#elif (XP_CONFIG_AGV_WHEEL_HCFA_ENABLE == 1)
#include "../driver/hcfa/hcfa.h"
struct hcfa_motor_attr hcfa_lwheel_attr = {
    .dir = 0, .rpm = 0,.acc = 500, .dec = 500,
    .io_ctrl = 1,  // 0 为IO控制  1为485控制
    .en_io = 4,       // IO控制对应的IO输出口
    .dir_io = 0,
    .emerg_io = 0
};
struct hcfa_motor_attr hcfa_rwheel_attr = {
    .dir = 0, .rpm = 0,.acc = 500, .dec = 500,
    .io_ctrl = 1,  // 0 为IO控制  1为485控制
    .en_io = 5,       // IO控制对应的IO输出口
    .dir_io = 0,
    .emerg_io = 0
};
#endif

/* 该表用于记录系统中 modbus 设备的相关信息 */
static struct xp_modbus_device xp_modbus_device_list[] = {
#if (XP_CONFIG_WASHCAR_LED_BANNER_ENABLE == 1)
    {.sid = 21, .name = "led_banner", .device_attr = NULL},
#endif
#if (XP_CONFIG_AGV_WHEEL_RS7020_ENABLE == 1)
    {.sid = 1, .name = "rs7020_leftwheel", .device_attr = &rs7020_lwheel_attr},
    {.sid = 2, .name = "rs7020_rightwheel", .device_attr = &rs7020_rwheel_attr},
#elif (XP_CONFIG_AGV_WHEEL_DMKE_ENABLE == 1)
    {.sid = 1, .name = "dmke_leftwheel", .device_attr = &dmke_lwheel_attr},
    {.sid = 2, .name = "dmke_rightwheel", .device_attr = &dmke_rwheel_attr},
#elif (XP_CONFIG_AGV_WHEEL_HCFA_ENABLE == 1)
    {.sid = 1, .name = "hcfa_leftwheel", .device_attr = &hcfa_lwheel_attr},
    {.sid = 2, .name = "hcfa_rightwheel", .device_attr = &hcfa_rwheel_attr},
#endif

    {},
};

/**
 * @brief 通过 modbus 的设备ID从modbus设备列表中查找对应的 modbus 设备对象
 * @param       sid: modbus 从设备的 id
 * @return      返回 modbus 设备对象的引用地址
 */
struct xp_modbus_device *get_modbus_device_by_sid(unsigned char sid)
{
    for (int i = 0; xp_modbus_device_list[i].sid != 0; i++)
    {
        if (xp_modbus_device_list[i].sid == sid)
            return &xp_modbus_device_list[i];
    }
    return NULL;
}
/**
 * @brief 通过 modbus 的设备名字从modbus设备列表中查找对应的 modbus 设备对象
 * @param       name: modbus 从设备的名字，对应到modbus设备对象的name属性
 * @return      返回 modbus 设备对象的引用地址
 */
struct xp_modbus_device *get_modbus_device_by_name(unsigned char *name)
{
    for (int i = 0; xp_modbus_device_list[i].sid != 0; i++)
    {
        if (0 == strcmp((char *)xp_modbus_device_list[i].name, (char *)name))
            return &xp_modbus_device_list[i];
    }
    return NULL;
}

/**
 * @brief 对系统中用到的设备进行初始化
 * @return      返回 0 表示所有设备均初始化成功
 */
int xp_common_device_init()
{
    int init_state = 0;
    init_state |= xp_modbus_485_port_init();

#if (XP_CONFIG_WASHCAR_LED_BANNER_ENABLE == 1)
    // led 屏幕初始化
    struct xp_modbus_device *xp_led_banner = get_modbus_device_by_name((unsigned char *)"led_banner");
    if (NULL != xp_led_banner)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, xp_led_banner);
        xp_led_banner->inited = xp_true;
    }
#endif
#if (XP_CONFIG_AGV_WHEEL_RS7020_ENABLE == 1)
    struct xp_modbus_device *rs7020_wheel = get_modbus_device_by_sid(1);
    if (NULL != rs7020_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, rs7020_wheel);
        rs7020_wheel->inited = xp_true;
    }
    rs7020_wheel = get_modbus_device_by_sid(2);
    if (NULL != rs7020_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, rs7020_wheel);
        rs7020_wheel->inited = xp_true;
    }
#elif (XP_CONFIG_AGV_WHEEL_DMKE_ENABLE == 1)
    struct xp_modbus_device *dmke_wheel = get_modbus_device_by_sid(1);
    if (NULL != dmke_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, dmke_wheel);
        dmke_wheel->inited = xp_true;
    }
    dmke_wheel = get_modbus_device_by_sid(2);
    if (NULL != dmke_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, dmke_wheel);
        dmke_wheel->inited = xp_true;
    }
#elif (XP_CONFIG_AGV_WHEEL_HCFA_ENABLE == 1)
    struct xp_modbus_device *hcfa_wheel = get_modbus_device_by_sid(1);
    if (NULL != hcfa_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, hcfa_wheel);
        hcfa_wheel->inited = xp_true;
    }
    hcfa_wheel = get_modbus_device_by_sid(2);
    if (NULL != hcfa_wheel)
    {
        init_state |= xp_modbus_device_mount(xp_modbus_485_port1, hcfa_wheel);
        hcfa_wheel->inited = xp_true;
    }
#endif

    if (init_state != 0)
        return -1;
    return 0;
}
